/**
 * Created by ajhin on 7/11/2015.
 */
package com.societyGames2.convert
{
import flash.utils.Dictionary;

import org.as3commons.asblocks.parser.antlr.LinkedListTree;

import org.as3commons.asblocks.parser.antlr.as3.AS3Parser;

public class TreeConverters
{
  private static var _typeToTreeConverter:Dictionary;
  private static var _childTreeConverter:ListTreeConverter = new ListTreeConverter("","");
  private static var _tokenTreeConverter:TokenTreeConverter = new TokenTreeConverter();
  private static var _unknownTreeConverter:DumpTreeConverter = new DumpTreeConverter();
  private static var _spaceSeparatedTreeConverter:ListTreeConverter = new ListTreeConverter("", "", " ");

  private static var _tabCount:int;
  private static var _tabs:Vector.<String> = new Vector.<String>();

  public static function initialize():void
  {
    _tabs.push("");

    _typeToTreeConverter = new Dictionary();
    add(AS3Parser.COMPILATION_UNIT, _childTreeConverter);
    add(AS3Parser.PACKAGE, new PackageTreeConverter());
    add(AS3Parser.TYPE, new ListTreeConverter("", "", "."));
    add(AS3Parser.IDENT, _tokenTreeConverter);
    add(AS3Parser.BLOCK, new AfterChildTreeConverter("{\n", "}", "\n", true));
    add(AS3Parser.IMPORT, new ListTreeConverter("using ", ";"));
    add(AS3Parser.ANNOTATIONS, new ListTreeConverter("", "", "\n"));
    add(AS3Parser.METATAG, new ListTreeConverter("[", "]"));
    add(AS3Parser.METATAG_PARAMS, new ListTreeConverter("(", ")", ", "));
    add(AS3Parser.ASSIGN, new ListTreeConverter("", "", " = "));
    add(AS3Parser.STRING_LITERAL, _tokenTreeConverter);
    add(AS3Parser.CLASS_DEF, new ClassDefTreeConverter());
    add(AS3Parser.INTERFACE_DEF, new InterfaceDefTreeConverter());
    add(AS3Parser.MODIFIERS, _spaceSeparatedTreeConverter);
    add(AS3Parser.PRIVATE, _tokenTreeConverter);
    add(AS3Parser.PUBLIC, _tokenTreeConverter);
    add(AS3Parser.INTERNAL, _tokenTreeConverter);
    add(AS3Parser.EXTENDS, _childTreeConverter);
    add(AS3Parser.IMPLEMENTS, _childTreeConverter);
    add(AS3Parser.TYPE_BLOCK, new ListTreeConverter("{\n", "}", "\n"));
    add(AS3Parser.FIELD_DEF, new ListTreeConverter("", ";", " "));
    add(AS3Parser.VAR, _childTreeConverter);
    add(AS3Parser.VAR_DEC, new VarDecTreeConverter());
    add(AS3Parser.TYPE_SPEC, _childTreeConverter);
    add(AS3Parser.DECIMAL_LITERAL, _tokenTreeConverter);
    add(AS3Parser.STATIC, _tokenTreeConverter);
    add(AS3Parser.FUNC_DEF, new FuncDefTreeConverter());
    add(AS3Parser.METHOD_DEF, new FuncDefTreeConverter());
    add(AS3Parser.ACCESSOR_ROLE, _childTreeConverter);
    add(AS3Parser.PARAMS, new ListTreeConverter("(", ")", ", "));
    add(AS3Parser.PARAM, new VarDecTreeConverter());
    add(AS3Parser.VOID, _tokenTreeConverter);
    add(AS3Parser.EXPR_STMNT, new ListTreeConverter("", ";"));
    add(AS3Parser.FUNCTION_CALL, _childTreeConverter);
    add(AS3Parser.ARGUMENTS, new ListTreeConverter("(", ")", ", "));
    add(AS3Parser.FIELD_ACCESS, new ListTreeConverter("", "", "."));
    add(AS3Parser.THIS, _tokenTreeConverter);
    add(AS3Parser.NEW, new ListTreeConverter("new ", ""));
    add(AS3Parser.NULL, _tokenTreeConverter);
    add(AS3Parser.IF, new ListTreeConverter("if ", ""));
    add(AS3Parser.CONDITION, new ListTreeConverter("(", ")"));
    add(AS3Parser.ELSE, new ListTreeConverter("else ", ""));
    add(AS3Parser.EQUAL, new ListTreeConverter("", "", "=="));
    add(AS3Parser.NOT_EQUAL, new ListTreeConverter("", "", "!="));
    add(AS3Parser.GT, new ListTreeConverter("", "", ">"));
    add(AS3Parser.GE, new ListTreeConverter("", "", ">="));
    add(AS3Parser.LT, new ListTreeConverter("", "", "<"));
    add(AS3Parser.LE, new ListTreeConverter("", "", "<="));
    add(AS3Parser.STRICT_EQUAL, new ListTreeConverter("", "", "==="));
    add(AS3Parser.STRICT_NOT_EQUAL, new ListTreeConverter("", "", "!==="));
  }

  public static function reset():void
  {
    _tabCount = 0;
  }

  public static function add(type:int, treeConverter:ITreeConverter):void
  {
    if (_typeToTreeConverter[type]!= null)
    {
      var tokenName:String = AS3Parser.tokenNames[type];
      throw new Error("Duplicate type: " + tokenName);
    }
    _typeToTreeConverter[type] = treeConverter;
  }

  private static function find(type:int):ITreeConverter
  {
    if (_typeToTreeConverter == null)
    {
      initialize();
    }
    var treeConverter:ITreeConverter = _typeToTreeConverter[type];
    return treeConverter != null ? treeConverter : _unknownTreeConverter;
  }

  public static function convert(linkedListTree:LinkedListTree):String
  {
    return find(linkedListTree.type).convert(linkedListTree);
  }

  public static function get childTreeConverter():ITreeConverter
  {
    return _childTreeConverter;
  }

  public static function get tokenTreeConverter():ITreeConverter
  {
    return _tokenTreeConverter;
  }

  public static function pushTab():void
  {
    _tabCount++;
    while (_tabCount >= _tabs.length)
    {
      _tabs.push(_tabs[_tabCount - 1] + "\t");
    }
  }

  public static function popTab():void
  {
    _tabCount--;
  }

  public static function getTabs():String
  {
    return _tabs[_tabCount];
  }
}
}
